local ui = require("ui")
local LevelScreen = display.newGroup()
local SpriteScreen = display.newGroup()
local mode = "normal"
local modeText = display.newText("0", 630, 10, native.systemFont, 30)
local distanceText = display.newText("0", 900, 600, native.systemFont, 30)
distanceText:setTextColor(255, 0, 0)
modeText:setTextColor(255, 0, 0)
modeText.text = mode
local travelDistance = 0;
distanceText.text = travelDistance
local dupInstance = nil
local scaleControl = nil

local levelText = display.newText("0", 780, 15, native.systemFont, 30)
levelText:setTextColor(255, 0, 0)
local levelIdx = 1
levelText.text = levelIdx
-- GUI
function setMode(val)
	if(val==mode) then
		return false
	end
	if( mode=="sprite") then
		SpriteScreen.isVisible = false
		LevelScreen.alpha = 1
	end
	if( mode=="dup" and dupInstance) then
		dupInstance.alpha = 1.0
		dupInstance = nil
	end
	if( (mode=="scale" or mode=="rotate") and scaleControl) then
		scaleControl.egTarget.alpha = 1.0
		scaleControl:removeSelf()
		scaleControl = nil
	end
	if(val=="sprite") then
		SpriteScreen.isVisible = true
		LevelScreen.alpha = 0.3
	end	
	
	mode = val
	modeText.text = mode
end
function onNewButtonPress(event)
	if( SpriteScreen.isVisible ) then
		setMode("normal")
	else
		setMode("sprite")
	end	
	return true
end
function onDupButtonPress(event)
	if( mode=="dup" ) then
		setMode("normal")
	else		
		setMode("dup")
	end
	return true
end
function onMoveButtonPress(event)
	if( mode=="move" ) then
		setMode("normal")
	else		
		setMode("move")
	end
	return true
end
function onRotateButtonPress(event)
	if( mode=="rotate" ) then
		setMode("normal")
	else		
		setMode("rotate")
	end
	return true
end
function onScaleButtonPress(event)
	if( mode=="scale" ) then
		setMode("normal")
	else		
		setMode("scale")
	end
	return true
end

function onDelButtonPress(event)
	if( mode=="del" ) then
		setMode("normal")
	else		
		setMode("del")
	end
	return true
end

function onNextButtonPress(event)	
	saveLevel()
	levelIdx = levelIdx+1
	levelText.text = levelIdx
	loadLevel()
	return true
end

function onBackButtonPress(event)	
	if( levelIdx > 1 ) then
		saveLevel()
		levelIdx = levelIdx-1
		levelText.text = levelIdx
		loadLevel()
	end
	return true
end

function onSaveButtonPress(event)	
	saveLevel()
	return true
end

local newButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onNewButtonPress,
						text = "New",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
newButton.x = 10
newButton.y = 30

local moveButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onMoveButtonPress,
						text = "Move",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
moveButton.x = newButton.x + 105
moveButton.y = 30

local rotateButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onRotateButtonPress,
						text = "Rotate",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
rotateButton.x = moveButton.x + 105
rotateButton.y = 30

local scaleButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onScaleButtonPress,
						text = "Scale",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
scaleButton.x = rotateButton.x + 105
scaleButton.y = 30

local dupButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onDupButtonPress,
						text = "Dup",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
dupButton.x = scaleButton.x + 105
dupButton.y = 30

local delButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onDelButtonPress,
						text = "Del",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
delButton.x = dupButton.x + 105
delButton.y = 30

local backButton = ui.newButton{
						default = "Resource/LevelEditorResource/back.png",
						over = "Resource/LevelEditorResource/back.png",
						onPress = onBackButtonPress,
					}
backButton.x = 760
backButton.y = 30

local nextButton = ui.newButton{
						default = "Resource/LevelEditorResource/next.png",
						over = "Resource/LevelEditorResource/next.png",
						onPress = onNextButtonPress,						
					}
nextButton.x = backButton.x + 60
nextButton.y = 30

local saveButton = ui.newButton{
						default = "Resource/LevelEditorResource/buttonBlue.png",
						over = "Resource/LevelEditorResource/buttonBlueOver.png",
						onPress = onSaveButtonPress,
						text = "Save",	
						textColor = { 0, 0, 0, 255 },
						size = 25,
					}
saveButton.x = nextButton.x + 120
saveButton.y = 30


SpriteScreen.isVisible = false

local Layers = display.newGroup()
LevelScreen:insert(Layers)

function updateTravelDistance()
	for i = 1, Layers.numChildren do		
		Layers[i].x = -travelDistance*Layers[i].egSpeed
	end
	distanceText.text = travelDistance
end
function readLayerFile()
	-- Read Layer data
	local file_name = string.format("%d.layer",levelIdx)
	local layer_path = system.pathForFile( file_name, system.DocumentsDirectory )
	local layer_fin = io.open( layer_path, "r" )
	if(layer_fin==nil) then
		return
	end
	while true do	
		local name_label,colon,layer_name = layer_fin:read(4,1,"*l")
		local speed_label,colon2,speed = layer_fin:read(5,1,"*n","*l")
		layer_fin:read("*l");
		
		if(name_label==nil) then
			break;
		end
		
		local layer = display.newGroup()
		layer.egName = layer_name
		--print(layer_name," ",speed)
		layer.egSpeed = speed
		Layers:insert(layer);			
		
	end
	layer_fin:close()
end
-------------------------------------------------------------
-- Read Sprite data
-------------------------------------------------------------

function onRotateScaleBtnTouch(event)
	local t = event.target		
	local phase = event.phase
	if "began" == phase then		
		-- Spurious events can be sent to the target, e.g. the user presses 
		-- elsewhere on the screen and then moves the finger over the target.
		-- To prevent this, we add this flag. Only when it's true will "move"
		-- events be sent to the target.
		t.isFocus = true
		-- Store initial position
		t.x0 = event.x - t.x
		t.y0 = event.y - t.y
		t.alpha = 0.3
	elseif t.isFocus then
		if "moved" == phase then
			-- Make object move (we subtract t.x0,t.y0 so that moves are
			-- relative to initial grab point, rather than object "snapping").
			t.x = event.x - t.x0
			t.y = event.y - t.y0
			
			if(mode=="scale") then
				local new_width = t.x - (t.egTarget.x - travelDistance*t.egTarget.parent.egSpeed)
				local new_height = t.egTarget.y - t.y			
				local xscale = new_width/ (t.egTarget.width*0.5)
				local yscale = new_height/ (t.egTarget.height*0.5)
				t.egTarget.xScale = xscale
				t.egTarget.yScale  = yscale
			end
			
			if(mode=="rotate") then
				local offsetY = t.y - t.egTarget.y
				local offsetX = t.x - (t.egTarget.x - travelDistance*t.egTarget.parent.egSpeed)		
				local angle_cos = -offsetY/ math.sqrt( offsetY*offsetY+offsetX*offsetX)
				local angle = math.acos(angle_cos)*180				
				if(offsetX<0) then
					angle = -angle
				end
				t.egTarget.rotation = angle
				
			end
		elseif "ended" == phase or "cancelled" == phase then			
			t.isFocus = false
			t.alpha = 1
		end
	end
end

function onSpriteIntanceTouch( event )
	
	local t = event.target		
	local phase = event.phase	
	
	if( mode=="sprite" or mode=="normal" ) then
		return false
	end
	
	if(mode=="scale" or mode=="rotate") then
		if "ended" == phase then
			if( scaleControl ) then
				scaleControl.egTarget.alpha = 1.0
				scaleControl:removeSelf()		
			end
			scaleControl = display.newImage("Resource/LevelEditorResource/controlBtn.png")
			
			if( mode=="scale" ) then
				scaleControl.x = t.x - travelDistance*t.parent.egSpeed + t.contentWidth *0.5
			else
				scaleControl.x = t.x - travelDistance*t.parent.egSpeed
			end
			scaleControl.y = t.y - t.contentHeight *0.5
			scaleControl.egTarget = t;
			t.alpha = 0.3
			scaleControl:addEventListener( "touch", onRotateScaleBtnTouch )
		end
	end
	
	if(mode=="dup") then
		if "ended" == phase then
			if( dupInstance ) then
				dupInstance.alpha = 1.0
			end
			dupInstance  = t;
			dupInstance.alpha = 0.3
		end
	end
	if(mode=="del") then
		if "began" == phase then
			t.alpha = 0.3
		end				
		if "moved" == phase then
			t.alpha = 1
		end
		if "ended" == phase or "cancelled" == phase then
			t.alpha = 1
			t:removeSelf()
		end
	end
	if(mode=="move") then		
		if "began" == phase then		
			-- Spurious events can be sent to the target, e.g. the user presses 
			-- elsewhere on the screen and then moves the finger over the target.
			-- To prevent this, we add this flag. Only when it's true will "move"
			-- events be sent to the target.
			t.isFocus = true
			-- Store initial position
			t.x0 = event.x - t.x
			t.y0 = event.y - t.y
			t.alpha = 0.3
		elseif t.isFocus then
			if "moved" == phase then
				-- Make object move (we subtract t.x0,t.y0 so that moves are
				-- relative to initial grab point, rather than object "snapping").
				t.x = event.x - t.x0
				t.y = event.y - t.y0
			elseif "ended" == phase or "cancelled" == phase then			
				t.isFocus = false
				t.alpha = 1
			end
		end
		-- Important to return true. This tells the system that the event
		-- should not be propagated to listeners of any objects underneath.		
	end
	return true
end

SpriteScreen.preview = nil


function createSpriteInstance(sprite_name,x,y,tuyetdoi)
	-- Find sprite
	local sprite = nil
	for i = 1, SpriteScreen.numChildren do	
		if( SpriteScreen[i].egName and sprite_name == SpriteScreen[i].egName ) then
			sprite = SpriteScreen[i]			
			break
		end
	end
	if( sprite==nil) then
		print("ERROR! Khong tim` thay sprite co ten la ",sprite_name)
		return
	end
	-- Create instance
	local layer_name = sprite.egLayer
	--print(sprite.egLayer)
	for i = 1, Layers.numChildren do
		if( Layers[i].egName == layer_name ) then
			local sprite_intance = display.newImage( sprite.egPath)
			if(tuyetdoi==true) then
				sprite_intance.x = x 
			else
				sprite_intance.x = x + travelDistance*Layers[i].egSpeed
			end
			sprite_intance:addEventListener("touch",onSpriteIntanceTouch)
			sprite_intance.y = y
			sprite_intance.egName = sprite.egName						
			Layers[i]:insert(sprite_intance)			
			return sprite_intance
		end
	end
	
end

function onSpritePress(event) 
	if( SpriteScreen.preview ) then
		if( SpriteScreen.preview.egName == event.button.egName) then
			createSpriteInstance(event.button.egName,400,200,false)
			setMode("normal")
		else
			SpriteScreen.preview:removeSelf()
			SpriteScreen.preview = nil
		end		
	end
	
	if( SpriteScreen.preview==nil) then
		SpriteScreen.preview = display.newImage( event.button.egPath)
		SpriteScreen.preview.x = 880
		SpriteScreen.preview.y = 200
		SpriteScreen.preview.egName = event.button.egName
		SpriteScreen.preview:scale( 150/SpriteScreen.preview.width, 150/SpriteScreen.preview.width )
		SpriteScreen:insert(SpriteScreen.preview)
	end	
	return true
end

function readSpriteFile()
	local file_name = string.format("%d.sprite",levelIdx)
	local sprite_path = system.pathForFile( file_name, system.DocumentsDirectory )
	local sprite_fin = io.open( sprite_path, "r" )
	local sprite_count = 0;
	if(sprite_fin==nil) then
		return
	end
	while true do	
		local name_label,colon,sprite_name = sprite_fin:read(4,1,"*l")
		local type_label,colon2,type_value = sprite_fin:read(4,1,"*l")
		local path_label,colon3,path_value = sprite_fin:read(4,1,"*l")
		local layer_label,colon4,layer_value = sprite_fin:read(5,1,"*l")	
		sprite_fin:read("*l");	
		if(name_label==nil) then
			break;
		end
		
		local sprite = ui.newButton{
							default = "Resource/LevelEditorResource/buttonOrange.png",
							over = "Resource/LevelEditorResource/buttonOrangeOver.png",
							onPress = onSpritePress,
							text = sprite_name,	
							textColor = { 0, 0, 0, 255 },
							size = 25,
						}
		sprite.x = 50 + math.fmod(sprite_count,4) * 210
		sprite.y = 80 + math.floor(sprite_count/4)* 50
		sprite.egName = sprite_name
		sprite.egType = type_value	
		sprite.egPath = path_value
		sprite.egLayer = layer_value
		
		-- DEBUG PRINT
		-- print(name_label,colon,sprite_name)
		-- print(type_label,colon2,type_value)
		-- print(path_label,colon3,path_value)
		-- print(layer_label,colon4,layer_value)
		-- print("")
		
		SpriteScreen:insert(sprite);		
		sprite_count = sprite_count+1
		
	end
	sprite_fin:close()
end

local normalStartDragX
function handleTouch(event) 
	local phase = event.phase
	event.x = event.x + travelDistance
	if( mode=="dup" and dupInstance ) then
		if( phase == "ended" ) then			
			local copy = createSpriteInstance(dupInstance.egName,event.x - travelDistance,event.y,false)
			copy.rotation = dupInstance.rotation
			copy.xScale = dupInstance.xScale
			copy.yScale = dupInstance.yScale
			if(copy==nil) then
				print("ERROR, cant dup!")
			else			
			end			
		end
	end
	
	if( mode=="normal") then		
		if( phase=="began" ) then
			normalStartDragX = event.x
		end		
		if( phase=="moved") then
			local delta = (normalStartDragX-event.x)*2
			travelDistance = travelDistance+delta;
			normalStartDragX= event.x+delta
			updateTravelDistance()			
		end
	end
	
end
Runtime:addEventListener( "touch", handleTouch )

-- SAVE LOAD
function saveLevel()
	local path = system.pathForFile( "data.txt", system.DocumentsDirectory )
 
-- io.open opens a file at path. returns nil if no file found
local file = io.open( path, "r" )	
	local file_name = string.format("%d.level",levelIdx)
	local file_path = system.pathForFile( file_name, system.DocumentsDirectory )
	local level_fin =  io.open( file_path, "w" )	
	level_fin:write(travelDistance,"\n")
	for i = 1, Layers.numChildren do		
		local layer = Layers[i]
		for j = 1, layer.numChildren do	
			level_fin:write( layer[j].egName, "\n",
							 layer[j].x,"\n",
							 layer[j].y,"\n",
							 layer[j].rotation,"\n",
							 layer[j].xScale,"\n",
							 layer[j].yScale,"\n")
		end
	end
	level_fin:close()
end

function clearLevel()	
	for i = 1, Layers.numChildren do		
		Layers[1]:removeSelf()
	end	
	for i = 1, SpriteScreen.numChildren do
		SpriteScreen[1]:removeSelf()
	end
end
function loadLevel()
	clearLevel()
	readLayerFile()
	readSpriteFile()	
	
	travelDistance = 0
	
	local file_name = string.format("%d.level",levelIdx)
	local file_path = system.pathForFile( file_name, system.DocumentsDirectory )
	local level_fin =  io.open( file_path, "r" )	
	
	if(level_fin==nil) then
		return
	end
	travelDistance = level_fin:read("*n","*l")
	while true do	
		local egName = level_fin:read("*l")
		local x = level_fin:read("*n","*l")
		local y = level_fin:read("*n","*l")
		local rotation = level_fin:read("*n","*l")
		local xScale = level_fin:read("*n","*l")
		local yScale = level_fin:read("*n","*l")
		if(egName==nil) then
			break;
		end
		local sprite_instance = createSpriteInstance(egName,x,y,true)
		sprite_instance.rotation = rotation
		sprite_instance.xScale = xScale
		sprite_instance.yScale = yScale		
		--print(egName," ",x," ",y," ")
		--print(rotation," ",xScale," ",yScale)		
	end
	updateTravelDistance()
	level_fin:close()
end

loadLevel()




